/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package sun.scheduler.io;

import sun.scheduler.core.resource.Resource;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.*;

import javax.swing.JFileChooser;
import javax.swing.filechooser.FileFilter;
import javax.swing.JOptionPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;

import sun.scheduler.core.*;
import sun.scheduler.core.job.DummyJob;
import sun.scheduler.core.job.Job;
import sun.scheduler.core.job.Job.CurveState;
import sun.scheduler.core.resource.Resource;
import sun.scheduler.core.resource.ResourceProfile;

/**
 * Class to write a new CSV schedule-file
 */
public class ScheduleWriter {

    /**
     * method to create a CSV-file filled with the information of processes in
     * an ArrayList
     *
     * @param filename - the name of the file you want to create
     * @param processes - ArrayList of processes you want to write into the file
     * @return true if successful, false otherwise
     */
    public static boolean writeProcessFile(String filename, ArrayList<Job> processes, Date startDate, CurveState cState) {
        BufferedWriter bwriter = null;

        try {

            // Construct the BufferedWriter object
            bwriter = new BufferedWriter(new FileWriter(filename));

            // Start writing to the output stream
            bwriter.write("Lfd. Nr;Vorgaenger;Name;Gruppennummer"
                    + ";Gruppenname;Ressourcenname;Anzahl der Ressourcen;Vorgangsdauer"
                    + ";Dauer ohne Einheit;Einheit Dauer;Ressourcennamen;Anfang;Vorgangsende"
                    + ";Arbeit;Arbeit ohne Dauer;Einheit Arbeit;");
            bwriter.newLine();
            for (int i = 0; i < processes.size(); i++) {
                
                if (processes.get(i) instanceof DummyJob) 
                    break;
                    
                writeProcessAttributes(bwriter, processes.get(i), startDate, cState);
            }

        } catch (FileNotFoundException ex) {
            ex.printStackTrace();
        } catch (IOException ex) {
            ex.printStackTrace();
        } finally {
            // Close the BufferedWriter
            try {
                if (bwriter != null) {
                    bwriter.flush();
                    bwriter.close();
                }
                return true;
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
        return false;

    }

    /**
     * method to create a CSV-file filled with the information of resources in
     * an ArrayList
     *
     * @param filename - the name of the file you want to create
     * @param processes - ArrayList of resources you want to write into the file
     * @return true if successful, false otherwise
     */
    public static boolean writeResourceFile(String filename, ArrayList<ResourceProfile> resis) {
        BufferedWriter bwriter = null;
        try {
            // Construct the BufferedWriter object
            bwriter = new BufferedWriter(new FileWriter(filename));

//            // Start writing to the output stream
            bwriter.write("Ressourcenname;Schichtmodell;Max. Einheiten;");
            bwriter.newLine();
            for (int i = 0; i < resis.size(); i++) {
                if (resis.get(i).getResource().info.name == "dummyRes") {
                    break;
                }
                writeResourceAttributes(bwriter, resis.get(i));
            }
        } catch (FileNotFoundException ex) {
            ex.printStackTrace();
        } catch (IOException ex) {
            ex.printStackTrace();
        } finally {
            // Close the BufferedWriter
            try {
                if (bwriter != null) {
                    bwriter.flush();
                    bwriter.close();
                }
                return true;
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
        return false;
    }

    /**
     * private method to write all attributes of a given process to one line (in
     * CSV-format) and goes to the next line after
     *
     * @param bwriter - the BufferedWriter
     * @param process - process object you want to examine
     * @throws IOException
     */
    private static void writeProcessAttributes(BufferedWriter bwriter, Job process, Date startDate, CurveState cState) {
        // Strings we want to write separated with ';'
        String c = ";", processId, predecessor, processName, groupId, groupName, resourceName, resourceQuantity, processDuration, resourceNameAndQuantity, processStart, processEnd, work, workWithoutDuration, workUnit;

        try {
            processId = "" + process.jobId;
            if (process.getPredecessors().size() <= 1) {
                predecessor = "" + intArrayListToString(process.getPredecessors());
            } else {
                predecessor = "\"";
                for (Integer i : process.getPredecessors()) {
                    predecessor += i + ";";
                }
                predecessor = predecessor.substring(0, predecessor.length() - 1) + "\"";
            }
            processName = "" + process.jobName;
            groupId = "" + process.groupId;
            groupName = "" + process.groupName;
            resourceName = "" + process.resource.info.name;
            resourceQuantity = ""+(int)process.getAmountOfResources(cState)  ;
            //TODO methode gibts noch nicht!
            processDuration = "" + process.getDuration(cState) + " Min.";
            resourceNameAndQuantity = "" + process.resource.info.name + "[" +(int)process.getAmountOfResources(cState)  + "]";
            Date d = startDate;
            SimpleDateFormat form = new SimpleDateFormat("dd.MM.yyyy HH:mm");
            processStart = "" + form.format(new Date(d.getTime() + process.getEarliestStartTime(cState) * 60000));
            processEnd = "" + form.format(new Date(d.getTime() + (process.getEarliestStartTime(cState)+process.getDuration(cState)) * 60000));
           
            work = "" + process.work + " Min.";
            
            workWithoutDuration = "" + process.work;
             workUnit = "Min.";
             
            

            // write a line
           
            bwriter.write("" + processId + c + predecessor + c + processName
                    + c + groupId + c + groupName + c + resourceName + c
                    + resourceQuantity + c + processDuration + c + process.getDuration(cState) + c
                    + "Min." + c + resourceNameAndQuantity + c + processStart + c
                    + processEnd + c + work + c + workWithoutDuration + c
                    + workUnit + c);
            // next line
            bwriter.newLine();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * private method to write all attributes of a given resource to one line
     * (in CSV-format) and goes to the next line after
     *
     * @param bwriter - the BufferedWriter
     * @param process - process object you want to examine
     * @throws IOException
     */
    private static void writeResourceAttributes(BufferedWriter bwriter, ResourceProfile res) {
        // Strings we want to write separated with ';'
        String c = ";", resourceName, resourceModel, maxUnit;

        try {

            resourceName = "" + res.getResource().info.name;
            resourceModel = "" + res.getResource().info.model;
            maxUnit = "" + res.getMaxCapacity();
            bwriter.write(resourceName + c + resourceModel + c + maxUnit + c);
            bwriter.newLine();

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * private method to write all items from an integer ArrayList in the form:
     * firstElement;secondElement;thirdElement;...;lastElement
     *
     * @param al - the integer ArrayList
     * @return a String containing all elements
     */
    private static String intArrayListToString(ArrayList<Integer> al) {
        String str = "";
        for (int i = 0; i < al.size(); i++) {
            if (i != 0) {
                str = str + ";";
            }
            str = str + al.get(i);
        }
        return str;
    }
    
    public static void writeResToFile(ArrayList<ResourceProfile> res) {
        // declare JFileChooser
        JFileChooser fileChooser = new JFileChooser();
        fileChooser.setDialogTitle("SAVE RESOURCE FILE");
        FileFilter filter = new FileFilter() {
            // overriding the accept method to accept the .csv files.

            @Override
            public boolean accept(File f) {
                return f.isDirectory() || f.getName().toLowerCase().endsWith(".csv");
            }

            @Override
            public String getDescription() {
                return "file type .csv is accepted only.";
            }
        };
        fileChooser.setFileFilter(filter);

        // let the user choose the destination file
        if (fileChooser.showSaveDialog(null) == JFileChooser.APPROVE_OPTION) {
            // indicates whether the user still wants to export the settings
            boolean doExport = true;

            // indicates whether to override an already existing file
            boolean overrideExistingFile = false;

            // get destination file
            File destinationFile = new File(fileChooser.getSelectedFile().getAbsolutePath());

            // check if file already exists
            while (doExport && destinationFile.exists() && !overrideExistingFile) {
                // let the user decide whether to override the existing file
                overrideExistingFile = (JOptionPane.showConfirmDialog(null, "The file " + fileChooser.getSelectedFile().getName() + " already exists!\nDo you want to replace it?", "Export Settings", JOptionPane.YES_NO_OPTION, 0) == JOptionPane.YES_OPTION);

                // let the user choose another file if the existing file shall not be overridden
                if (!overrideExistingFile) {
                    if (fileChooser.showSaveDialog(null) == JFileChooser.APPROVE_OPTION) // get new destination file
                    {
                        destinationFile = new File(fileChooser.getSelectedFile().getAbsolutePath());
                    } else // seems like the user does not want to export the settings any longer
                    {
                        doExport = false;
                    }
                }
            }

            // perform the actual export
            if (doExport) {
                String filename = fileChooser.getSelectedFile().getAbsolutePath();
                writeResourceFile(filename, res);
            }
        }
        
    }

    public static void writeToFile(ArrayList<Job> processes, Date startDate, CurveState cState) {
        // declare JFileChooser
        JFileChooser fileChooser = new JFileChooser();
        fileChooser.setDialogTitle("SAVE JOB FILE");
        FileFilter filter = new FileFilter() {
            // overriding the accept method to accept the .csv files.

            @Override
            public boolean accept(File f) {
                return f.isDirectory() || f.getName().toLowerCase().endsWith(".csv");
            }

            @Override
            public String getDescription() {
                return "file type .csv is accepted only.";
            }
        };
        fileChooser.setFileFilter(filter);

        // let the user choose the destination file
        if (fileChooser.showSaveDialog(null) == JFileChooser.APPROVE_OPTION) {
            // indicates whether the user still wants to export the settings
            boolean doExport = true;

            // indicates whether to override an already existing file
            boolean overrideExistingFile = false;

            // get destination file
            File destinationFile = new File(fileChooser.getSelectedFile().getAbsolutePath());

            // check if file already exists
            while (doExport && destinationFile.exists() && !overrideExistingFile) {
                // let the user decide whether to override the existing file
                overrideExistingFile = (JOptionPane.showConfirmDialog(null, "The file " + fileChooser.getSelectedFile().getName() + " already exists!\nDo you want to replace it?", "Export Settings", JOptionPane.YES_NO_OPTION, 0) == JOptionPane.YES_OPTION);

                // let the user choose another file if the existing file shall not be overridden
                if (!overrideExistingFile) {
                    if (fileChooser.showSaveDialog(null) == JFileChooser.APPROVE_OPTION) // get new destination file
                    {
                        destinationFile = new File(fileChooser.getSelectedFile().getAbsolutePath());
                    } else // seems like the user does not want to export the settings any longer
                    {
                        doExport = false;
                    }
                }
            }

            // perform the actual export
            if (doExport) {
                String filename = fileChooser.getSelectedFile().getAbsolutePath();
                writeProcessFile(filename, processes, startDate, cState);
            }
        }


    }

    /**
     * private method to write all attributes of a given process to one line in
     * a JTable(!) (in CSV-format) and goes to the next line after
     *
     * @param bwriter - the BufferedWriter
     * @param process - process object you want to examine
     * @throws IOException
     */
    public static void writeProcessAttributesToJTable(JTable jTable, ArrayList<Job> processes, Date startDate, CurveState cState) {
        // Strings we want to write separated with ';'
        String c = ";", processId, predecessor, processName, groupId, groupName, resourceName, resourceQuantity, processDuration, resourceNameAndQuantity, processStart, processEnd, work, workWithoutDuration, workUnit;
        String columnName = "Lfd. Nr;Vorgaenger;Name;Gruppennummer"
                + ";Gruppenname;Ressourcenname;Anzahl der Ressourcen;Vorgangsdauer"
                + ";Dauer ohne Einheit;Einheit Dauer;Ressourcennamen;Anfang;Vorgangsende"
                + ";Arbeit;Arbeit ohne Dauer;Einheit Arbeit;";
        DefaultTableModel tableModel = new DefaultTableModel(null, columnName.split(";"));

        try {
            jTable.setModel(tableModel);
            for (Job process : processes) {
                /* TODO interface DummyJob + JobInfo anpassen 
                 * 
                if (!(process instanceof DummyJob)) { 
                * 
                */
                    processId = "" + process.jobId;
                    if (process.getPredecessors().size() <= 1) {
                        predecessor = "" + intArrayListToString(process.getPredecessors());
                    } else {
                        predecessor = "\"";
                        for (Integer i : process.getPredecessors()) {
                            predecessor += i + ";";
                        }
                        predecessor = predecessor.substring(0, predecessor.length() - 1) + "\"";
                    }
                    processName = "" + process.jobName;
                    groupId = "" + process.groupId;
                    groupName = "" + process.groupName;
                    resourceName = "" + process.resource.info.name;
                    resourceQuantity = ""+(int)process.getAmountOfResources(cState) ;
                    processDuration = "" + process.getDuration(cState) + " Min.";

                    resourceNameAndQuantity = "" + process.resource.info.name + "[" +(int)process.getAmountOfResources(cState) + "]";
                    Date d = startDate;
                    SimpleDateFormat form = new SimpleDateFormat("dd.MM.yyyy HH:mm");
                    processStart = "" + form.format(new Date(d.getTime() + process.getEarliestStartTime(cState) * 60000));
                    processEnd = "" + form.format(new Date(d.getTime() + (process.getEarliestStartTime(cState)+process.getDuration(cState)) * 60000));
                    work = "" + process.work + " Min.";
                    workWithoutDuration = "" + process.work;
                    workUnit = "Min.";

                    // write a line
                    String[] str = new String[16];
                    str[0] = processId;
                    str[1] = predecessor.replace("\"", "");
                    str[2] = processName;
                    str[3] = groupId;
                    str[4] = groupName;
                    str[5] = resourceName;
                    str[6] = resourceQuantity;
                    str[7] = processDuration;
                    str[8] = process.getDuration(cState)+"";
                    str[9] = " Min.";
                    str[10] = resourceNameAndQuantity;
                    
                    str[11] = processStart;
                    str[12] = processEnd;
                    
                    str[13] = work;
                    str[14] = workWithoutDuration;
                    str[15] = workUnit;
                    // next line
                    tableModel.addRow(str);
                }
            /*
             }
             * 
             */
            tableModel.fireTableDataChanged();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
